﻿using System;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.UI;
using Channelvn.Cached.Common;

namespace Channelvn.Cached.Base
{
    public class PageBase : Page
    {
        private static readonly Assembly _currentAssembly = Assembly.GetExecutingAssembly();

        public string PageCacheName
        {
            get
            {
                if (Lib.QueryString.NewsID == 0)
                    return string.Format(Constants.CACHE_NAME_FORMAT_HTML_PAGE_CONTENT, Lib.QueryString.ZoneID, Lib.QueryString.NewsID, Lib.QueryString.ThreadID, Lib.QueryString.PageIndex, Lib.QueryString.ViewByDate);
                else
                    return string.Format(Constants.CACHE_NAME_FORMAT_HTML_PAGE_CONTENT, 0, Lib.QueryString.NewsID, Lib.QueryString.ThreadID, Lib.QueryString.PageIndex, Lib.QueryString.ViewByDate);
            }
        }

        protected override void OnPreLoad(EventArgs e)
        {
            CacheSettings settings = CacheSettings.GetCurrentSettings();
            // Read all settings ok
            if (settings.PageSettings.Length > 0)
            {
                CacheSettings.PageSetting pageSetting = settings.GetPageSetting(Request.FilePath);
                // Read page setting ok
                if (!string.IsNullOrEmpty(pageSetting.CacheName))
                {
                    base.EnableViewState = pageSetting.EnableViewState;

                    // Get Control settings
                    for (int i = 0; i < pageSetting.ControlSettings.Length; i++)
                    {
                        HtmlControlCacheBase cache = (HtmlControlCacheBase)_currentAssembly.CreateInstance(pageSetting.ControlSettings[i].Assembly, false, BindingFlags.CreateInstance, null, new object[] { pageSetting.ControlSettings[i] }, System.Globalization.CultureInfo.CurrentCulture, null);

                        if (null != cache)
                        {
                            cache.UpdateCache(this);
                        }
                    }
                }
            }

            base.OnPreLoad(e);
        }

        // Find control in master page and inner page
        //private Control FindControlRecursive(Control root, string id)
        //{
        //    if (root.ID == id) return root;

        //    for (int i = 0; i < root.Controls.Count; i++)
        //    {
        //        Control foundCtl = FindControlRecursive(root.Controls[i], id);

        //        if (foundCtl != null) return foundCtl;
        //    }
        //    return null;
        //}

        protected override void Render(HtmlTextWriter writer)
        {
            StringBuilder strBuilder = new StringBuilder();
            using (StringWriter strWriter = new StringWriter(strBuilder))
            {
                string sVirURL = (null != HttpContext.Current.Items["VirtualUrl"] ? HttpContext.Current.Items["VirtualUrl"].ToString() : "");

                using (RewriteFormHtmlTextWriter htmlWriter = new RewriteFormHtmlTextWriter(strWriter, sVirURL))
                {
                    base.Render(htmlWriter);

                    string html = strBuilder.ToString();
                    if (ConfigurationManager.AppSettings["AllowWrite1Line"] == "1")
                    {
                        html = html.Replace("\t", " ");
                        html = html.Replace("    ", " ");
                        html = html.Replace("  ", " ");
                        html = html.Replace(Environment.NewLine, " ");
                    }
                    writer.Write(html);
                    if (CacheController.IsAllowDistributedCached)
                    {
                        CacheSettings settings = CacheSettings.GetCurrentSettings();
                        CacheSettings.PageSetting pageSetting = settings.GetPageSetting(Request.FilePath);

                        if (!IsPostBack && pageSetting.EnableCache && pageSetting.UpdateCacheByWeb)
                        {
                            if (!string.IsNullOrEmpty(pageSetting.Category))
                            {
                                CacheController.Add(pageSetting.Category, PageCacheName, html, pageSetting.CacheExpire);
                            }
                            else
                            {
                                if (Lib.QueryString.NewsID == 0)
                                    CacheController.Add(PageCacheName, html, pageSetting.CacheExpire);
                                else if (html.Length >= 54000)
                                {
                                    // Với bài viết, thì mình sẽ set cache với các bài từ 2013 trở đi vào cổng -3. 
                                   CacheController.Add(Constants.NEWS_DETAIL_PAGE_CACHE, PageCacheName, html, 3600);
                                }
                            }
                        }
                    }
                }
            }
        }

        private class RewriteFormHtmlTextWriter : HtmlTextWriter
        {
            private string _formAction;

            public RewriteFormHtmlTextWriter(System.IO.TextWriter writer)
                : base(writer)
            {

            }
            public RewriteFormHtmlTextWriter(System.IO.TextWriter writer, string action)
                : base(writer)
            {
                if (!string.IsNullOrEmpty(action))
                {
                    this._formAction = action;
                }
            }

            public override void RenderBeginTag(string tagName)
            {
                if (tagName.IndexOf("form") >= 0)
                {
                    base.RenderBeginTag(tagName);
                }
            }

            public override void WriteAttribute(string name, string value, bool fEncode)
            {
                if ("action" == name && !string.IsNullOrEmpty(this._formAction))
                {
                    value = this._formAction;
                }
                base.WriteAttribute(name, value, fEncode);
            }
        }
    }
}
